Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

[core] Replace mbgl::MapChange with mbgl::MapObserver #8377

Merged
merged 7 commits into from
Mar 15, 2017

Conversation

brunoabinader
Copy link
Member

Implements mbgl::MapObserver, replacing mbgl::MapChange enumerator and mbgl::Backend::notifyMapChange. Now mbgl::Backend inherits from mbgl::MapObserver, which provides non-pure virtual equivalents for the enumerator items.

Caveats:

  • Qt preserves the QMapboxGL::MapChange enumerator from the public API.
  • Android refactor still requires mbgl::MapChange - this is not necessary but finishing up this platform refactor can happen on a separate PR. Once we finish cleaning up the Android platform, then we can safely remove mbgl::MapChange source code entirely.

Added suggested reviewers for platform-specific patches as well as core changes - please replace yourself with someone else from the mobile team otherwise.

Fixes #6383.

@brunoabinader brunoabinader added Core The cross-platform C++ core, aka mbgl GLFW iOS Mapbox Maps SDK for iOS macOS Mapbox Maps SDK for macOS Node.js node-mapbox-gl-native Qt Mapbox Maps SDK for Qt, aka Qt Location Mapbox GL refactor labels Mar 13, 2017
@brunoabinader brunoabinader self-assigned this Mar 13, 2017
@mention-bot
Copy link

@brunoabinader, thanks for your PR! By analyzing this pull request, we identified @1ec5, @tmpsantos and @friedbunny to be potential reviewers.

@brunoabinader brunoabinader force-pushed the map-observer branch 3 times, most recently from b3a3780 to de9c074 Compare March 13, 2017 15:41
return mapObserver;
}

virtual void onRegionWillChange() {}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggest s/Region/Camera/g.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ack. For now I'm abstaining from renaming the public APIs for Qt & Android. For iOS & macOS I'm adding entries to CHANGELOG.md about the renaming.

Copy link
Contributor

@1ec5 1ec5 Mar 14, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renaming the public API for iOS and macOS would be a backwards-incompatible change that would require a major version bump. Fortunately, this PR doesn’t touch the public API (MGLMapView.h) at all, only the internal implementation of MGLMapView (MGLMapView.mm), so no changelog entry is required.

}

virtual void onRegionWillChange() {}
virtual void onRegionWillChangeAnimated() {}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense to provide a boolean (or two-valued-enum) parameter to on*Change , rather than having separate on*Change and on*ChangeAnimated methods? Similarly with on*Rendering{Frame,Map}/on*Rendering{Frame,Map}FullyRendered.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think so - I'm adding two enums to MapObserver: CameraChangeMode and RenderMode.

virtual void onWillStartRenderingFrame() {}
virtual void onDidFinishRenderingFrame() {}
virtual void onDidFinishRenderingFrameFullyRendered() {}
virtual void onWillStartRenderingMap() {}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a useful difference between on*RenderingFrame and on*RenderingMap?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

onWillStartRenderingMap() and onDidFinishRenderingMap() are based on MapKit’s -[MKMapViewDelegate mapViewWillStartRenderingMap:] (“when one or more tiles are revealed and require rendering”) and -[MKMapViewDelegate mapViewDidFinishRenderingMap:fullyRendered:] (“finishes rendering all of the currently visible tiles to the best of its ability”), which have analogues in our iOS and macOS SDKs.

If our iOS documentation is to be believed, on*RenderingFrame() would be called on each frame of a camera animation or property transition, even where no additional tiles need to be fetched and displayed. However, I don’t know for sure if that’s how we’ve implemented these notifications, given #2775.

/cc @friedbunny

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In terms of usefulness, we’ve found the “rendering frame” notifications to be useful in situations where the developer wants to synchronize a view atop the map or override some annotation view behavior that we apply on every frame. But the “rendering map” notifications remain more generally useful for knowing when it’s safe to snapshot a map view or have the UI change once the map is quiescent.

- (void)notifyMapChange:(mbgl::MapChange)change
{
// Ignore map updates when the Map object isn't set.
- (void)onRegionWillChange:(bool)animated {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In Objective-C, use BOOL (YES/NO) instead of bool (true/false).

- (void)notifyMapChange:(mbgl::MapChange)change
{
// Ignore map updates when the Map object isn't set.
- (void)onRegionWillChange:(bool)animated {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove “on” from the names of this method and others like it. Also, ensure that there’s a word before the parameter that describes the parameter, so that the meaning of the YES or NO is apparent at the call site: -regionWillChangeAnimated:.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-cameraWillChangeAnimated: would also be acceptable.

The macOS SDK implementation of MGLMapViewDelegate already uses the term “camera” instead of “region”. The iOS SDK implementation blindly copied MapKit’s use of “region” without bringing over MapKit’s MKRegion struct.

We’ll want to fix the public interface when we’re ready for backwards-incompatible changes, but for now, either name works for this internal method.

break;
}
case mbgl::MapChangeSourceDidChange:
- (void)onRegionIsChanging {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-regionIsChanging:

}
}

- (void)onRegionDidChange:(bool)animated {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-regionDidChangeAnimated:

}
}

- (void)onWillStartLoadingMap {
Copy link
Contributor

@1ec5 1ec5 Mar 13, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-mapViewWillStartLoadingMap

}
}

- (void)onDidFinishRenderingMap:(bool)fullyRendered {
Copy link
Contributor

@1ec5 1ec5 Mar 13, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-mapViewDidFinishRenderingMapFullyRendered:

}
}

- (void)onDidFinishLoadingStyle {
Copy link
Contributor

@1ec5 1ec5 Mar 13, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-mapViewDidFinishLoadingStyle

}
}

- (void)onSourceDidChange {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

iOS doesn’t need to do anything in response to source changes, since attribution is displayed on-demand. You can safely remove this method and make its caller a no-op.

}
}

- (void)onSourceDidChange {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pass in the mbgl::style::Source and rename this method to -sourceDidChange:.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm 👍 with the renaming, but I'd prefer to defer the source argument change as a platform-specific change meant to a separate PR in the same way @tobrun did in #8389 for Android.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#8397

}

void Map::Impl::onStyleError() {
backend.notifyMapChange(MapChangeDidFailLoadingMap);
observer.onDidFailLoadingMap();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should plumb res.error through to here or implement onResourceError() instead to allow the SDKs to provide more information about the failure. Currently, in order to fudge parity with MapKit, the iOS and macOS SDKs have to synthesize an uninformative NSError, but res.error’s message field would be perfect for this purpose.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above, I'd prefer if we could move this to a platform-specific refactor.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This suggestion isn’t platform-specific but rather an improvement on the code being added in this PR. Tracking in #8398.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see - thanks for the clarification. Let's handle this in #8398 👍

Copy link
Member

@tobrun tobrun left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Android side of things is 👍 , ticketed follow up ticket to migrate the android code base to this system in #8389.

Copy link
Contributor

@1ec5 1ec5 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

iOS and macOS changes look good. Looking forward to the core improvements in #8397 and especially #8398.

@@ -1167,7 +1167,8 @@ - (void)touchesBegan:(__unused NS_SET_OF(UITouch *) *)touches withEvent:(__unuse
}

- (void)notifyGestureDidBegin {
[self notifyMapChange:mbgl::MapChangeRegionWillChange];
bool animated = false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/bool/BOOL/ and s/false/NO/ (×2)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit confused - I've seen bool usage when the code is a glue between C++ and Objective-C, and BOOL on Objective-C code along this source file - should we open an issue then to fix this for all remaining bools?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I think I got it now - this function is not part of the C++ glue and thus should use the Objective-C notation - got it :) Fixing now.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 As a rule of thumb, in Objective-C++ code, if you’re inside an Objective-C class or category (look for @implementation and @end), use Objective-C types; if you’re inside a C++ class or struct, use C++ types. There are some exceptions: for example, I find it useful to use static_cast over C-style casts throughout Objective-C++ code. And std::vector can often be faster than NSMutableArray. This article suggests some more ways C++ can improve Objective-C code, but a lot of it is a matter of preference.

@brunoabinader
Copy link
Member Author

Qt public API refactor handled in #8419.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Core The cross-platform C++ core, aka mbgl iOS Mapbox Maps SDK for iOS macOS Mapbox Maps SDK for macOS Node.js node-mapbox-gl-native Qt Mapbox Maps SDK for Qt, aka Qt Location Mapbox GL refactor
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants